package time;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.LongAdder;

@Slf4j
public class TimeTest3 {

    private static final ExecutorService executor = Executors.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors()
    );

    private static final int count1 = 100;
    private static final int count2 = 1_000_000;

    public static void main(String[] args) throws InterruptedException {

        double avr1 = 0, avr2 = 0;

        for (int i = 0; i < count1; i++) {
            long t1 = getRunTime(System::currentTimeMillis);
            long t2 = getSingleRunTime(System::currentTimeMillis);
            log.info("System.currentTimeMillis, 多线程用时：{} ns", t1);
            log.info("System.currentTimeMillis, 单线程用时：{} ns", t2);
            avr1 += 1.0 * t1 / count1;
            avr2 += 1.0 * t2 / count1;
        }

        log.info("System.currentTimeMillis, 多线程平均用时：{} ns", avr1);
        log.info("System.currentTimeMillis, 单线程平均用时：{} ns", avr2);

        executor.shutdown();
    }

    private static long getRunTime(Runnable run) throws InterruptedException {
        var latch = new CountDownLatch(TimeTest3.count2);
        var adder = new LongAdder();

        for (int i = 0; i < TimeTest3.count2; i++) {
            executor.execute(() -> {
                try {
                    long start = System.nanoTime();
                    run.run();
                    long end = System.nanoTime();
                    adder.add(end - start);
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        return adder.sum();
    }

    private static long getSingleRunTime(Runnable run) {
        long adder = 0;

        for (int i = 0; i < TimeTest3.count2; i++) {
            long start = System.nanoTime();
            run.run();
            long end = System.nanoTime();
            adder += (end - start);
        }

        return adder;
    }
}
